#include "databasemanager.h"
#include <QSqlQuery> // 包含执行 SQL 语句的类
#include <QSqlError> // 包含处理数据库错误的类
#include <QDateTime> // 用于获取当前时间
#include <QThread>
#include <QDateTime>
#include <QVariantMap>

DatabaseManager::DatabaseManager(QObject *parent)
    : QObject{parent}
{
    // 在构造函数中调用初始化函数
    initDatabase();
    // 在数据库成功打开后，添加这条日志
    if (m_db.isOpen()) {
        qDebug() << "[DB CONSTRUCTOR] DatabaseManager instance" << this
                 << "created and DB opened on THREAD:" << QThread::currentThread();
    }
}


DatabaseManager::~DatabaseManager()
{
    // 在程序退出时，析构函数会被调用，此时关闭数据库连接
    qDebug() << "[DB DESTRUCTOR] Destroying DatabaseManager instance" << this
             << "on THREAD:" << QThread::currentThread();
    if (m_db.isOpen())
    {
        m_db.close();
        qDebug() << "close database";
    }
}

void DatabaseManager::initDatabase()
{
    // 每个连接都需要一个独一无二的连接名
    // 基于线程ID的指针地址来创建，保证唯一性
    const QString connectionName = QString("conn_%1").arg(reinterpret_cast<quintptr>(QThread::currentThread()));

    // 关键逻辑：
    // 检查这个唯一的连接名是否已经被添加到全局连接池中
    if (QSqlDatabase::contains(connectionName)) {
        // 如果已存在，直接获取这个连接的句柄
        m_db = QSqlDatabase::database(connectionName, false); // false表示不打开
    } else {
        // 如果不存在，才添加一个新的连接配置
        m_db = QSqlDatabase::addDatabase("QSQLITE", connectionName);
        // 配置数据库文件名，这个配置会被全局连接池记住
        m_db.setDatabaseName("qtalk.db");
    }

    // 无论连接是新创建的还是获取的，我们都需要为当前线程打开它
    if (!m_db.open())
    {
        qWarning() << "Database Error: Failed to open database:" << m_db.lastError().text()
        << "on thread:" << QThread::currentThreadId();
        return;
    }

    qDebug() << "Database connected successfully on thread:" << QThread::currentThreadId();

    // 创建 Users 表的逻辑保持不变，但要确保 query 使用的是当前线程的连接
    if (m_db.tables().contains("Users"))
    {
        qDebug() << "Users table already exists.";
        //表明已经创建过了。
    } else
    {
        QSqlQuery query(m_db);
        QString createTableSql = R"(
            CREATE TABLE IF NOT EXISTS Users (
                user_id INTEGER PRIMARY KEY AUTOINCREMENT,
                username TEXT UNIQUE NOT NULL,
                password_hash TEXT NOT NULL,
                creation_date TEXT NOT NULL
            );
        )";

        if (!query.exec(createTableSql)) {
            qWarning() << "Database Error: Failed to create Users table:" << query.lastError().text();
        } else {
            qDebug() << "Users table is ready.";
        }
    }

    // 检查 Friends 表是否存在
    if (!m_db.tables().contains("Friends"))
    {
        QSqlQuery query(m_db);
        QString createFriendsTableSql = R"(
        CREATE TABLE IF NOT EXISTS Friends (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            user1_id INTEGER NOT NULL,
            user2_id INTEGER NOT NULL,
            FOREIGN KEY(user1_id) REFERENCES Users(user_id),
            FOREIGN KEY(user2_id) REFERENCES Users(user_id),
            UNIQUE (user1_id, user2_id)
        );
    )";
        if (!query.exec(createFriendsTableSql))
        {
            qWarning() << "Database Error: Failed to create Friends table:" << query.lastError().text();
        }
        else
        {
            qWarning() << "Friends table created.";
        }
    }

    return ;
}


bool DatabaseManager::registerUser(const QString &username, const QString &passwordHash)
{
    QSqlQuery query(m_db); // <--- 创建查询时，传入数据库连接
    // 使用预处理语句 (Prepared Statements) 来防止 SQL 注入，这是非常重要的安全实践
    query.prepare("INSERT INTO Users (username, password_hash, creation_date) "
                  "VALUES (:username, :password_hash, :creation_date)");

    query.bindValue(":username", username);
    query.bindValue(":password_hash", passwordHash);
    query.bindValue(":creation_date", QDateTime::currentDateTime().toString(Qt::ISODate));

    if (!query.exec()) {
        // 如果执行失败，很可能是因为用户名重复 (UNIQUE 约束)
        qWarning() << "Failed to register user:" << username
                   << "Error:" << query.lastError().text();
        return false;
    }

    qDebug() << "User registered successfully:" << username;
    return true;
}

int DatabaseManager::validateUser(const QString &username, const QString &passwordHash)
{
    QSqlQuery query(m_db); // <--- 创建查询时，传入数据库连接
    query.prepare("SELECT user_id, password_hash FROM Users WHERE username = :username");
    query.bindValue(":username", username);

    if (!query.exec()) {
        qWarning() << "User validation query failed for:" << username
                   << "Error:" << query.lastError().text();
        return 0;
    }

    // query.next() 会将光标移动到第一条（也是唯一一条）结果上
    // 如果没有结果（用户名不存在），.next() 会返回 false
    if (query.next())
    {
        // 先按名称获取，更健壮
        QString storedHash = query.value("password_hash").toString();

        if (storedHash == passwordHash) {
            qDebug() << "User validation successful for:" << username;
            // 现在结果集里有 "user_id" 这一列了，可以安全地获取它
            return query.value("user_id").toInt();
        }
    }

    qDebug() << "User validation failed for:" << username;
    return 0; // 用户名不存在或密码不匹配
}

QList<QVariantMap> DatabaseManager::getFriends(int userId)
{
    QList<QVariantMap> friends;
    QSqlQuery query(m_db);
    // 一个复杂的查询，它会找出所有与 userId 相关的记录，并获取对方的信息
    query.prepare(R"(
        SELECT U.user_id, U.username FROM Users U
        INNER JOIN Friends F ON (U.user_id = F.user2_id AND F.user1_id = :userId) OR
                               (U.user_id = F.user1_id AND F.user2_id = :userId)
    )");
    query.bindValue(":userId", userId);

    if (!query.exec())
    {
        qWarning() << "Failed to query friends for user" << userId << ":" << query.lastError().text();
        return friends;
    }

    while (query.next())
    {
        QVariantMap friendData;
        friendData["user_id"] = query.value("user_id").toInt();
        friendData["username"] = query.value("username").toString();
        friends.append(friendData);
    }
    return friends;
}

int DatabaseManager::getUserId(const QString& username)
{
    QSqlQuery query(this->m_db);
    query.prepare("SELECT user_id FROM Users WHERE username = :username");
    query.bindValue(":username", username);
    if (query.exec() && query.next()) {
        return query.value(0).toInt(); // 找到了，返回ID
    }
    return -1;
}

QString DatabaseManager::getUsername(int userId)
{
    QSqlQuery query(m_db);
    query.prepare("SELECT username FROM Users WHERE user_id = :id");
    query.bindValue(":id", userId);
    if (query.exec() && query.next()) {
        return query.value(0).toString();
    }
    return QString(); // 返回空字符串表示未找到
}

bool DatabaseManager::areAlreadyFriends(int userId1, int userId2)
{
    QSqlQuery query(m_db);
    // 查询时，让小ID在前，大ID在后，以匹配我们存储的规则
    if (userId1 > userId2)
    {
        std::swap(userId1, userId2);
    }
    query.prepare("SELECT 1 FROM Friends WHERE user1_id = :id1 AND user2_id = :id2");
    query.bindValue(":id1", userId1);
    query.bindValue(":id2", userId2);
    return query.exec() && query.next(); // 如果能查到记录，说明已经是好友
}

bool DatabaseManager::addFriend(int userId1, int userId2)
{
    // --- 新增的检查步骤 ---
    // 1. 先检查他们是否已经是好友
    if (areAlreadyFriends(userId1, userId2))
    {
        qDebug() << "Info: Users" << userId1 << "and" << userId2 << "are already friends. No action needed.";
        return true; // 直接返回成功，因为已经是好友关系了
    }
    // --- 检查结束 ---

    // 2. 如果不是好友，再执行插入操作
    if (userId1 > userId2)
    {
        std::swap(userId1, userId2);
    }

    QSqlQuery query(m_db);
    query.prepare("INSERT INTO Friends (user1_id, user2_id) VALUES (:id1, :id2)");
    query.bindValue(":id1", userId1);
    query.bindValue(":id2", userId2);

    if (!query.exec())
    {
        qWarning() << "Database INSERT failed for adding friend:" << query.lastError();
        return false;
    }

    return true;
}

QVariantMap DatabaseManager::getUserInfo(int userId)
{
    QVariantMap userInfo;
    QSqlQuery query(m_db);
    query.prepare("SELECT user_id, username FROM Users WHERE user_id = :id");
    query.bindValue(":id", userId);
    if (query.exec() && query.next())
    {
        userInfo["user_id"] = query.value("user_id").toInt();
        userInfo["username"] = query.value("username").toString();
    }
    return userInfo;
}
